var os = require('os');
var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g

var utils = {
  // 获取本机在网络中的ip 地址
  getIPAdress: function(){
    var interfaces = require('os').networkInterfaces();　　
    for (var devName in interfaces) {　　　　
      var iface = interfaces[devName];　　　　　　
      for (var i = 0; i < iface.length; i++) {
        var alias = iface[i];
        if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
          return alias.address;
        }
      }　　
    }
  },
  base64clean: function(str){
    // Node takes equal signs as end of the Base64 encoding
    str = str.split('=')[0]
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = str.trim().replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  },
  // 数字转HEX
  toHex: function(n){
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  },
  // utf-8编码的字符转bytes
  utf8ToBytes: function(string, units){
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
    for (var i = 0; i < length; ++i) {
      codePoint = string.charCodeAt(i)

      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }

          // valid lead
          leadSurrogate = codePoint

          continue
        }

        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }

        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }

      leadSurrogate = null

      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
    return bytes
  },
  // ascii编码的字符转bytes
  asciiToBytes: function(str, ){
    var byteArray = []
    for (var i = 0; i < str.length; ++i) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  },
  utf16leToBytes:  function(str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; ++i) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  },
  base64ToBytes: function(str) {
    return base64.toByteArray(base64clean(str))
  },
  blitBuffer: function(src, dst, offset, length) {
    for (var i = 0; i < length; ++i) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  },
  // 是不是数组类型
  isArray: function(arg) {
    if (Array.isArray) {
      return Array.isArray(arg);
    }
    return objectToString(arg) === '[object Array]';
  },
  // 是不是布尔类型
  isBoolean: function(arg) {
    return typeof arg === 'boolean';
  },
  // 是不是Null类型
  isNull: function(arg) {
    return arg === null;
  },
  // 是不是NullOrUndefined
  isNullOrUndefined: function(arg) {
    return arg == null;
  },
  // 是不是Number类型
  isNumber: function(arg) {
    return typeof arg === 'number';
  },
  // 是不是字符串类型
  isString: function(arg) {
    return typeof arg === 'string';
  },
  // 是不是symbol类型
  isSymbol: function(arg) {
    return typeof arg === 'symbol';
  },
  // 是不是undefined类型
  isUndefined: function(arg) {
    return arg === void 0;
  },
  // 是不是RegExp类型
  isRegExp: function(re) {
    return objectToString(re) === '[object RegExp]';
  },
  // 是不是object类型
  isObject: function(arg) {
    return typeof arg === 'object' && arg !== null;
  },
  // 是不是Date类型
  isDate: function(d) {
    return objectToString(d) === '[object Date]';
  },
  // 是不是Error类型
  isError: function(e) {
    return (objectToString(e) === '[object Error]' || e instanceof Error);
  },
  // 是不是function类型
  isFunction: function(arg) {
    return typeof arg === 'function';
  },
  // 是不是基本数据类型
  isPrimitive: function(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  },
  // 对象转字符串
  objectToString: function(o) {
    return Object.prototype.toString.call(o);
  }
}


module.exports = utils;
